package com.zt.bus.wx.controller;

import com.github.binarywang.wxpay.bean.request.WxEntPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxEntPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.google.gson.Gson;
import com.monkeyk.os.domain.oauth.AccessToken;
import com.zt.bus.alipay.util.PayUtil;
import com.zt.bus.constant.BusConstant;
import com.zt.bus.order.model.OrderPayment;
import com.zt.bus.order.service.OrderPaymentService;
import com.zt.bus.wx.service.WxService;
import com.zt.bus.wx.util.ReturnModel;
import com.zt.bus.wx.util.Sha1Util;
import com.zt.bus.wx.util.WxUtil;
import com.zt.bus.wx.util.XmlUtil;
import com.zt.servlet.Response;
import com.zt.shiro.GlobalInput;
import com.zt.user.api.UserApi;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * 微信支付Controller
 * <p>
 * Created by FirenzesEagle on 2016/6/20 0020.
 * Email:liumingbo2008@gmail.com
 */
@Controller
@RequestMapping(value = "/wxMpPay")
public class WxMpPayController {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private WxPayConfig payConfig;
	@Autowired
	private WxPayService payService;

	@Autowired
	protected WxMpService wxMpService;

	@Autowired
	private OrderPaymentService orderPaymentService;

	/**
	 * 用于返回预支付的结果 WxMpPrepayIdResult，一般不需要使用此接口
	 *
	 * @param response
	 * @param request
	 * @throws WxErrorException
	 */
	@RequestMapping(value = "/getPrepayIdResult")
	public void getPrepayId(HttpServletResponse response,
	                        HttpServletRequest request) throws WxErrorException {
		WxPayUnifiedOrderRequest payInfo = new WxPayUnifiedOrderRequest();
		payInfo.setOpenid(request.getParameter("openid"));
		payInfo.setOutTradeNo(request.getParameter("out_trade_no"));
		payInfo.setTotalFee(Integer.valueOf(request.getParameter("total_fee")));
		payInfo.setBody(request.getParameter("body"));
		payInfo.setTradeType(request.getParameter("trade_type"));
		payInfo.setSpbillCreateIp(request.getParameter("spbill_create_ip"));
		payInfo.setNotifyURL("");
		this.logger
				.info("PartnerKey is :" + this.payConfig.getMchKey());
		WxPayUnifiedOrderResult result = this.payService.unifiedOrder(payInfo);
		this.logger.info(new Gson().toJson(result));
		WxUtil.renderString(response, result);
	}

	/**
	 * 返回前台H5调用JS支付所需要的参数，公众号支付调用此接口
	 *
	 * @param response
	 * @param request
	 */
	@RequestMapping(value = "/getJSSDKPayInfo")
	@ResponseBody
	public JSONObject getJSSDKPayInfo(HttpServletResponse response,
	                            HttpServletRequest request) {
		logger.info("公众号支付开始");
		ReturnModel returnModel = new ReturnModel();
		WxPayUnifiedOrderRequest prepayInfo = new WxPayUnifiedOrderRequest();

		//openid
		String openid = request.getParameter("openId");
		//订单id
		String orderId = request.getParameter("orderId");

		//TODO 得到openid和phone
		String phone = GlobalInput.getCurrentUserId();

		OrderPayment orderPayment = orderPaymentService.getOrderPayment(BusConstant.PayPlatform.WEIXIN_WEB, orderId, phone);

		prepayInfo.setOpenid(openid);
		prepayInfo.setOutTradeNo(orderPayment.getTradeNo());
//		prepayInfo.setTotalFee((int) (orderPayment.getCashAmount() * 100)); // 单位分

//		prepayInfo.setOutTradeNo(PayUtil.getTradeNo());
		prepayInfo.setTotalFee(2);

		prepayInfo.setBody("定制公交订单号:" + orderId);
		prepayInfo.setTradeType(BusConstant.Wx.TRADE_TYPE_MP);
		prepayInfo.setSpbillCreateIp(PayUtil.getRemoteAddrIp(request));
		//TODO(user) 填写通知回调地址
		prepayInfo.setNotifyURL(BusConstant.Wx.WX_MP_NOTIFY_URL);

		JSONObject returnJson = new JSONObject();
		try {
			Map<String, String> payInfo = this.payService.getPayInfo(prepayInfo);
			payInfo.put("tradeNo",orderPayment.getTradeNo());
			returnModel.setResult(true);
			returnModel.setDatum(payInfo);
			returnJson = WxUtil.renderJson(response, returnModel);
		} catch (WxErrorException e) {
			returnModel.setResult(false);
			returnModel.setReason(e.getError().toString());
			returnJson = WxUtil.renderJson(response, returnModel);
			this.logger.error(e.getError().toString());
		}
		//插入支付记录
		orderPaymentService.createOrderPayment(orderPayment);
		logger.info("公众号支付结束");
		return Response.responseSuccess(returnJson);
	}

	/**
	 * 微信通知支付结果的回调地址，notify_url
	 *
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/getJSSDKCallbackData")
	public void getJSSDKCallbackData(HttpServletRequest request,
	                                 HttpServletResponse response) {
		logger.info("公众号回调开始");
		try {
			synchronized (this) {
				Map<String, String> kvm = XmlUtil.parseRequestXmlToMap(request);
				String transaction_id = kvm.get("transaction_id");//微信公众号支付返回的交易号
				String tradeNo = kvm.get("out_trade_no");
				if (SignUtils.checkSign(kvm, this.payConfig.getMchKey())) {
					if (kvm.get("result_code").equals("SUCCESS")) {
						orderPaymentService.paymentSetResult(tradeNo,transaction_id,true,kvm.get("out_trade_no") + " 支付成功!");
						logger.info("out_trade_no: " + kvm.get("out_trade_no") + " pay SUCCESS!");
						response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
					} else {
						orderPaymentService.paymentSetResult(tradeNo,transaction_id,true,tradeNo + " result_code 失败!");
						this.logger.error("out_trade_no: "
								+ kvm.get("out_trade_no") + " result_code is FAIL");
						response.getWriter().write(
								"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[result_code is FAIL]]></return_msg></xml>");
					}
				} else {
					orderPaymentService.paymentSetResult(tradeNo,transaction_id,true,tradeNo + " 签名失败!");
					response.getWriter().write(
							"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[check signature FAIL]]></return_msg></xml>");
					this.logger.error("out_trade_no: " + kvm.get("out_trade_no")
							+ " check signature FAIL");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("公众号回调结束");
	}

	@RequestMapping(value = "/entPay")
	public void payToIndividual(HttpServletResponse response,
	                            HttpServletRequest request) {
		WxEntPayRequest wxEntPayRequest = new WxEntPayRequest();
		wxEntPayRequest.setAppid(payConfig.getAppId());
		wxEntPayRequest.setMchId(payConfig.getMchId());
		wxEntPayRequest.setNonceStr(Sha1Util.getNonceStr());
		wxEntPayRequest.setPartnerTradeNo(request.getParameter("partner_trade_no"));
		wxEntPayRequest.setOpenid(request.getParameter("openid"));
		wxEntPayRequest.setCheckName("NO_CHECK");
		wxEntPayRequest.setAmount(Integer.valueOf(request.getParameter("amount")));
		wxEntPayRequest.setDescription(request.getParameter("desc"));
		wxEntPayRequest.setSpbillCreateIp(request.getParameter("spbill_create_ip"));

		try {
			WxEntPayResult wxEntPayResult = payService.entPay(wxEntPayRequest);
			if ("SUCCESS".equals(wxEntPayResult.getResultCode().toUpperCase())
					&& "SUCCESS"
					.equals(wxEntPayResult.getReturnCode().toUpperCase())) {
				this.logger.info("企业对个人付款成功！\n付款信息：\n" + wxEntPayResult.toString());
			} else {
				this.logger.error("err_code: " + wxEntPayResult.getErrCode()
						+ "  err_code_des: " + wxEntPayResult.getErrCodeDes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "/index")
	public String index(HttpServletRequest request, HttpServletResponse response,
						@RequestParam(value = "code") String code) throws ServletException, IOException {
		ReturnModel returnModel = new ReturnModel();
		try {
			WxMpOAuth2AccessToken accessToken = this.wxMpService.oauth2getAccessToken(code);
			WxMpUser wxMpUser = this.wxMpService.getUserService()
					.userInfo(accessToken.getOpenId(), BusConstant.Wx.LANG);
			returnModel.setResult(true);
			returnModel.setDatum(wxMpUser);
			String openId = wxMpUser.getOpenId();
			JSONObject userInfoJson = WxUtil.renderJson(response, returnModel);
			System.out.println("zlh:" + userInfoJson);

			return "redirect:/weixin/" + request.getParameter("redirect") + "?openId=" + openId;
		} catch (WxErrorException e) {
			returnModel.setResult(false);
			returnModel.setReason(e.getError().toString());
			WxUtil.renderString(response, returnModel);
			this.logger.error(e.getError().toString());
		}

		return "redirect:/403.do";
	}

}

